package com.jeeplus.ht.common;

import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import com.jeeplus.config.properties.JeePlusProperites;
import com.jeeplus.ht.entity.FileEntity;
import com.jeeplus.mob.common.DateUtil;
import com.jeeplus.mob.common.StringHelper;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;



public class FileUploadTool {
 
	TransfMediaTool transfMediaTool = new TransfMediaTool();
	// 文件最大50M
	private static long upload_maxsize = 50 * 1024 * 1024;
	// 文件允许格式
	//其他文件格式
	private static String[] allowFiles = { ".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".xlsx",".xls",".ppt"
			,".gif",".png", ".jpg", ".jpeg",".bmp",".mp4", ".flv",".avi",".mpg",".wmv",".3gp", ".mov", ".asf", 
			".asx", ".vob",".wmv9", ".rm", ".rmvb",".mp3",".wma",".flac",".aac,",".mmf",".amr,",".m4a",".m4r",".ogg",".eav",".wv"};
	private static String[] otherFiles = { ".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".xlsx",".xls",".ppt"};
	//图片格式
	private static String[] picFiles = {".gif",".png", ".jpg", ".jpeg",".bmp"};
	//视频格式
	private static String[] vidoFiles = {".mp4", ".flv",".avi",".mpg",".wmv",".3gp", ".mov", ".asf", ".asx", ".vob",".wmv9", ".rm", ".rmvb"};
	//音频格式
	private static String[] audioFiles = {".mp3",".wma",".flac",".aac,",".mmf",".amr,",".m4a",".m4r",".ogg",".eav",".wv"};
	// 允许转码的视频格式（ffmpeg）
	private static String[] allowFLV = { ".avi", ".mpg", ".wmv", ".3gp", ".mov", ".asf", ".asx", ".vob" };
	// 允许的视频转码格式(mencoder)
	private static String[] allowAVI = { ".wmv9", ".rm", ".rmvb" };

	public FileEntity createFile(MultipartFile multipartFile, HttpServletRequest request) {
		FileEntity entity = new FileEntity();
		boolean bflag = false;
		//1、图片 2视频 3音频 4其他文件  
		String fileType = "";
		String Folder = "pic";
		String fileName = multipartFile.getOriginalFilename().toString();
		// 判断文件不为空
		if (multipartFile.getSize() != 0 && !multipartFile.isEmpty()) {
			bflag = true;
			// 判断文件大小
			if (multipartFile.getSize() <= upload_maxsize) {
				bflag = true;
				// 文件类型判断
				fileType = this.checkFileType(fileName);
				if (!fileType.equals("")) {
					if (fileType.equals("picFiles")){
						Folder =  "pic";
					}
					if (fileType.equals("vidoFiles")){
						Folder =  "vidio";
					}
					if (fileType.equals("audioFiles")){
						Folder =  "audio";
					}
					if (fileType.equals("otherFiles")){
						Folder =  "fils";
					}
					bflag = true;
				} else {
					bflag = false;
					entity.setMsg("文件类型不允许");
					System.out.println("文件类型不允许");
				}
			} else {
				bflag = false;
				entity.setMsg("文件大小超范围");
				System.out.println("文件大小超范围");
			}
		} else {
			bflag = false;
			entity.setMsg("文件为空");
			System.out.println("文件为空");
		}
		if (bflag) {
			String logoPathDir = "/FileUpload/"+Folder+"/"+ DateUtil.dateToStr(new Date(), 2);
			String logoRealPathDir = JeePlusProperites.newInstance().getUserfilesBaseDir();
			logoRealPathDir = logoRealPathDir + logoPathDir;
			File logoSaveFile = new File(logoRealPathDir);
			if (!logoSaveFile.exists()) {
				logoSaveFile.mkdirs();
			}
			String name = fileName.substring(0, fileName.lastIndexOf("."));
			System.out.println("文件名称：" + name);
			// 新的文件名 --上传后的文件名称
			String newFileName = StringHelper.GetGUID();
			// 文件扩展名
			String fileEnd = this.getFileExt(fileName);
			// 绝对路径 -- 原图的文件地址
			String fileNamedirs = logoRealPathDir + File.separator + newFileName + fileEnd;
//			//压缩后的 名称
//			String newFileName1 = StringHelper.GetGUID();
			//压缩后的地址
			String compressPath = logoRealPathDir + File.separator + newFileName + fileEnd;
			System.out.println("保存的绝对路径：" + fileNamedirs);
			File filedirs = new File(fileNamedirs);
			// 转入文件
			try {
				multipartFile.transferTo(filedirs);
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (fileEnd.equalsIgnoreCase(".jpg") || fileEnd.equalsIgnoreCase(".png") || fileEnd.equalsIgnoreCase(".jpeg")){
				long srcFileSize = filedirs.length();
				System.out.println("图片的大小是："+srcFileSize / 1024+"kb");
				if (srcFileSize / 1024 > 800){//800kb
					int Width = getImgWidth(filedirs);
					int Height = getImgHeight(filedirs);
					if (Width == -1 || Height == -1){
//						toName = name;
					} else {
						System.out.println("图片的宽是："+Width+"，高是："+Height);
						commpressPicForScale(fileNamedirs, compressPath, 800, 0.8);
					}
				}
			}
			// 相对路径
			entity.setType(fileEnd);
			String fileDir = logoPathDir +"/"+ newFileName + fileEnd;
			//压缩后的图片 相对路径
			String compressDir = logoPathDir +"/"+ newFileName + fileEnd;
//			StringBuilder builder = new StringBuilder(fileDir);
			String finalFileDir = fileDir;
			// size存储为String
			String size = this.getSize(filedirs);
			// 源文件保存路径
			String aviPath = filedirs.getAbsolutePath();
			// 转码Avi
			// boolean flag = false;
			if (this.checkAVIType(fileEnd)) {
				// 设置转换为AVI格式后文件的保存路径
				String codcAviPath = logoRealPathDir + File.separator + newFileName + ".avi";
				// 获取配置的转换工具（mencoder.exe）的存放路径
				String mencoderPath = request.getSession().getServletContext().getRealPath("/tools/mencoder.exe");
				aviPath = transfMediaTool.processAVI(mencoderPath, filedirs.getAbsolutePath(), codcAviPath);
				fileEnd = this.getFileExt(codcAviPath);
			}
			if (aviPath != null) {
				// 转码Flv
				if (this.checkMediaType(fileEnd)) {
					try {
						// 设置转换为flv格式后文件的保存路径
						String codcFilePath = logoRealPathDir + File.separator + newFileName + ".flv";
						// 获取配置的转换工具（ffmpeg.exe）的存放路径
						String ffmpegPath = request.getSession().getServletContext().getRealPath("/tools/ffmpeg.exe");
						transfMediaTool.processFLV(ffmpegPath, aviPath, codcFilePath);
						fileEnd = ".flv";
						fileDir = logoPathDir +"/"+ newFileName + ".flv";
//						builder = new StringBuilder(fileDir);
						finalFileDir = fileDir;
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				entity.setFileType(fileType);
				entity.setSize(size);
				entity.setPath(finalFileDir);//原图路径
				entity.setCompressDir(compressDir);//压缩后的路径
				entity.setTitleOrig(name);
				entity.setTitleAlter(newFileName+fileEnd);
				Timestamp timestamp = new Timestamp(System.currentTimeMillis());
				entity.setUploadTime(timestamp);
				return entity;
			} else {
				return entity;
			}
		} else {
			return entity;
		}

	}

	/**
	 * 文件类型判断
	 *
	 * @param fileName
	 * @return
	 */
	private String checkFileType(String fileName) {
		String fileType = "";
		Iterator<String> type = Arrays.asList(otherFiles).iterator();
		while (type.hasNext()) {
			String ext = type.next();
			System.out.println(ext);
			if (fileName.toLowerCase().endsWith(ext)) {
				fileType = "4";
				return fileType;
			}
		}
		Iterator<String> type1 = Arrays.asList(picFiles).iterator();
		while (type1.hasNext()) {
			String ext = type1.next();
			System.out.println(ext);
			if (fileName.toLowerCase().endsWith(ext)) {
				fileType = "1";
				return fileType;
			}
		}
		Iterator<String> type2 = Arrays.asList(vidoFiles).iterator();
		while (type2.hasNext()) {
			String ext = type2.next();
			System.out.println(ext);
			if (fileName.toLowerCase().endsWith(ext)) {
				fileType = "2";
				return fileType;
			}
		}
		Iterator<String> type3 = Arrays.asList(audioFiles).iterator();
		while (type3.hasNext()) {
			String ext = type3.next();
			System.out.println(ext);
			if (fileName.toLowerCase().endsWith(ext)) {
				fileType = "3";
				return fileType;
			}
		}
		return fileType;
	}

	/**
	 * 视频类型判断(flv)
	 *
	 * @param fileEnd
	 * @return
	 */
	private boolean checkMediaType(String fileEnd) {
		Iterator<String> type = Arrays.asList(allowFLV).iterator();
		while (type.hasNext()) {
			String ext = type.next();
			if (fileEnd.equals(ext)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 视频类型判断(AVI)
	 *
	 * @param fileEnd
	 * @return
	 */
	private boolean checkAVIType(String fileEnd) {
		Iterator<String> type = Arrays.asList(allowAVI).iterator();
		while (type.hasNext()) {
			String ext = type.next();
			if (fileEnd.equals(ext)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 获取文件扩展名
	 *
	 * @return string
	 */
	private String getFileExt(String fileName) {
		return fileName.substring(fileName.lastIndexOf("."));
	}

	/**
	 * 依据原始文件名生成新文件名
	 * 
	 * @return
	 */
	private String getName(String fileName) {
		Iterator<String> type = Arrays.asList(allowFiles).iterator();
		while (type.hasNext()) {
			String ext = type.next();
			if (fileName.contains(ext)) {
				String newFileName = fileName.substring(0, fileName.lastIndexOf(ext));
				return newFileName;
			}
		}
		return "";
	}

	/**
	 * 文件大小，返回kb.mb
	 *
	 * @return
	 */
	private String getSize(File file) {
		String size = "";
		long fileLength = file.length();
		DecimalFormat df = new DecimalFormat("#.00");
		if (fileLength < 1024) {
			size = df.format((double) fileLength) + "BT";
		} else if (fileLength < 1048576) {
			size = df.format((double) fileLength / 1024) + "KB";
		} else if (fileLength < 1073741824) {
			size = df.format((double) fileLength / 1048576) + "MB";
		} else {
			size = df.format((double) fileLength / 1073741824) + "GB";
		}
		return size;
	}


	
	/**
     * Get the Mime Type from a File
     * @param fileName 文件名
     * @return 返回MIME类型
     * thx https://www.oschina.net/question/571282_223549
     * add by fengwenhua 2017年5月3日09:55:01
     */
    public static String getMimeType(String fileName) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String type = fileNameMap.getContentTypeFor(fileName);
        return type;
    }
    
    public boolean delAttach(String AttachPath,HttpServletRequest request){
    	String logoRealPathDir = JeePlusProperites.newInstance().getUserfilesBaseDir();
		String filePath = logoRealPathDir + AttachPath;
		File fileTemp = new File(filePath);
		// 判断文件是否存在
		boolean falg = false;
		falg = fileTemp.exists();
		if (falg) {
			if (true == fileTemp.isFile()) {
				boolean flag = false;
				flag = fileTemp.delete();
				if (flag) {
					System.out.println("删除成功！");
					return true;
				}
			} else {
				System.out.println("不是文件！");
				return false;
			}
		} else {
			System.out.println("文件不存在！");
			return false;
		}
		return false;
    }
    
    //图片压缩
    public static String thumbnailFile (String filePath,MultipartFile imageFile) {
    	 if(filePath.contains(".png")){
    		 filePath = filePath.replace(".png", ".jpg");
         }
         long size = imageFile.getSize();
         double scale = 1.0d ;
         if(size >= 200*1024){
             if(size > 0){
            	 if(size >= 200*1024 && size < 500*1024){//小于500K的时候
                     scale = 0.9f ;             
                 }
                 if(size >= 500*1024 && size < 800*1024){//小于800K的时候
                     scale = 0.8f ;             
                 }
                 if(size >= 800*1024 && size < 1 *1024 * 1024){//小于1M的时候
                     scale = 0.7f ;             
                 }
                 if(size >= 1 *1024 * 1024 && size < 2 *1024 * 1024){//小于2M的时候
                     scale = 0.6f ;             
                 }
                 if(size >= 2 *1024 * 1024 && size < 3 *1024 * 1024){//小于3M的时候
                     scale = 0.5f ;             
                 }
                 if(size >= 3 *1024 * 1024 && size < 5 *1024 * 1024){//小于3M的时候
                     scale = 0.4f ;             
                 }
                 if(size >= 5 *1024 * 1024){//大于等于5M的时候
                     scale = 0.3f ;             
                 }
             }
             System.out.println("压缩比例为为："+scale);
         }
         try {
             if(size < 200*1024){
                 Thumbnails.of(filePath).scale(1f).outputFormat("jpg").toFile(filePath);
             }else{
                 Thumbnails.of(filePath).scale(1f).outputQuality(scale).outputFormat("jpg").toFile(filePath);
             }
         } catch (Exception e1) {
        	 
         }
        return filePath;
    }
    
    /**
     * 根据指定大小和指定精度压缩图片
     * 
     * @param srcPath
     *            源图片地址
     * @param desPath
     *            目标图片地址
     * @param desFileSize
     *            指定图片大小，单位kb
     * @param accuracy
     *            精度，递归压缩的比率，建议小于0.9
    *             目标最大宽度
    *             目标最大高度
     * @return 目标文件路径
     */
   public static String commpressPicForScale(String srcPath, String desPath,
           long desFileSize, double accuracy) {
       if (StringHelper.IsEmptyOrNull(srcPath) || StringHelper.IsEmptyOrNull(srcPath)) {
           return null;
       }
       if (!new File(srcPath).exists()) {
           return null;
       }
       try {
           File srcFile = new File(srcPath);
           long srcFileSize = srcFile.length();
           System.out.println("源图片：" + srcPath + "，大小：" + srcFileSize / 1024
                                       + "kb");
           //获取图片信息
           BufferedImage bim = ImageIO.read(srcFile);
           int srcWidth = bim.getWidth();
           int srcHeight = bim.getHeight();

           //先转换成jpg
		   Thumbnails.Builder builder = Thumbnails.of(srcFile).outputFormat("png");

           // 指定大小（宽或高超出会才会被缩放）
//           if(srcWidth > desMaxWidth || srcHeight > desMaxHeight) {
//               builder.size(desMaxWidth, desMaxHeight);
//           }else{
               //宽高均小，指定原大小
               builder.size(srcWidth,srcHeight);
//           }

           // 写入到内存
           ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
           builder.toOutputStream(baos);

           // 递归压缩，直到目标文件大小小于desFileSize
           byte[] bytes = commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);

           // 输出到文件
           File desFile = new File(desPath);
           FileOutputStream fos = new FileOutputStream(desFile);
           fos.write(bytes);
           fos.close();

           System.out.println("目标图片：" + desPath + "，大小" + desFile.length() / 1024 + "kb");
           System.out.println("图片压缩完成！");
       } catch (Exception e) {
           e.printStackTrace();
           return null;
       }
       return desPath;
   }

   private static byte[] commpressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException {
      // File srcFileJPG = new File(desPath);
       long srcFileSizeJPG = bytes.length;
       // 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩
       if (srcFileSizeJPG <= desFileSize * 1024) {
           return bytes;
       }
       // 计算宽高
       BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
       int srcWdith = bim.getWidth();
       int srcHeigth = bim.getHeight();
       int desWidth = new BigDecimal(srcWdith).multiply(
                               new BigDecimal(accuracy)).intValue();
       int desHeight = new BigDecimal(srcHeigth).multiply(
                               new BigDecimal(accuracy)).intValue();

       ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
       Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy).toOutputStream(baos);
       return commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);
   }
   
   /**
    * 获取图片宽度
    * @param file  图片文件
    * @return 宽度
    */
   public static int getImgWidth(File file) {
       InputStream is = null;
       BufferedImage src = null;
       int ret = -1;
       try {
           is = new FileInputStream(file);
           src = ImageIO.read(is);
           ret = src.getWidth(null); // 得到源图宽
           is.close();
       } catch (Exception e) {
           e.printStackTrace();
       }
       return ret;
   }
     
     
   /**
    * 获取图片高度
    * @param file  图片文件
    * @return 高度
    */
   public static int getImgHeight(File file) {
       InputStream is = null;
       BufferedImage src = null;
       int ret = -1;
       try {
           is = new FileInputStream(file);
           src = ImageIO.read(is);
           ret = src.getHeight(null); // 得到源图高
           is.close();
       } catch (Exception e) {
           e.printStackTrace();
       }
       return ret;
   }

	public static File multipartFileToFile(MultipartFile file) throws Exception {

		File toFile = null;
		if (file.equals("") || file.getSize() <= 0) {
			file = null;
		} else {
			InputStream ins = null;
			ins = file.getInputStream();
			toFile = new File(file.getOriginalFilename());
			inputStreamToFile(ins, toFile);
			ins.close();
		}
		return toFile;
	}

	//获取流文件
	private static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
   }



	}